[Chapter4] HTTP2 프로토콜 기초 (1)

HTTP/2 IN ACTION을 공부하며 정리한 글입니다.
틀린 부분은 지적해주시면 감사드리겠습니다 😀

HTTP/2

왜 1.2가 아닐까?

HTTP/1.1에서 HTTP/1.2가 아닌 HTTP/2로 넘어간 이유는 무엇일까? 앞에서 다룬 내용과 같이, HTTP/2는 HTTP/1의 성능 문제를 해결하고자 만들어졌다. 헤더 압축, 서버 푸시, 스트림 등 이러한 변경 사항은, 하위 프로토콜의 하위 호완을 완전히 깨뜨리는 변경이다. 때문에 HTTP/2는 주요 버전 업그레이드로 간주된다.

텍스트 대신 바이너리

HTTP/1은 완전히 텍스트 기반이지만, HTTP/2는 바이너리 패킷 기반 프로토콜이다. HTTP/1은 요청을 보낼 때 텍스트 형태로 요청을 보낸다. 텍스트의 경우 사람이 보기 좋지만, 컴퓨터가 해석하기에는 어렵다는 단점이 있다. 하지만 HTTP/2는 텍스트가 아닌 바이너리(2진수)로 변환이 된다.

즉, 사람이 읽기 쉬운 텍스트(문자열) 형태 대신, 컴퓨터가 이해하기 쉬운 2진수 형태로 데이터를 주고 받는 것이다.

동기적이기보다는 다중화된 프로토콜

HTTP/1은 동기적이고, 단일 요청 및 응답 프로토콜이다. 즉, 클라이언트가 여러 요청을 보내면, 요청을 보낸 순서대로 응답을 받고, 기다리게 되는 것이다. 이 과정에서 HOL(Head of line) Blocking 이슈도 생겼다. 이를 우회하기 위한 방법이 나왔지만, 자체의 문제와 비효율성이 뒤따랐다.

HTTP/2의 경우 단일 TCP 커넥션만으로, 여러 요청을 동시에 병렬로 처리한다.

Image

그림을 보면 알 수 있듯이, HTTP/1은 요청을 보낼 때마다 TCP 커넥션을 만들고, 응답이 올 때까지 다른 요청을 보낼 수 없지만, HTTP/2는 단일 TCP 환경에서 스트림을 통해 요청을 보내고, 응답이 오기 전에도 또 다른 요청을 계속해서 보낼 수 있다.

  • 프레임
    • HTTP/2에서 데이터를 보내는 가장 작은 단위
    • 프레임의 타입은 HEADERS, DATA, SETTING와 같이 고정된 타입을 가짐
    • 각 프레임은 해당 타입에 맞는 정형화된 데이터 조각을 담고 있음
  • 스트림
    • 하나의 요청/응답을 처리하기 위한 통로
    • 요청마다 각각의 고유한 ID 번호를 가짐
    • 여러 개의 프레임으로 구성

즉, 이 스트림이라는 통로는 프레임이라는 작고 정형화된 데이터 블록으로 구성되며, 각각의 프레임은 헤더, 바디, 설정 정보 등을 나눠 전송하는 것이다.

헤더 압축

HTTP/1의 경우 여러 요청을 보낼 때마다 동일한 헤더가 계속 반복된다. 예를 들어, Cookie, Host, Accept 등이 있다. 한 마디로, 계속해서 공간이 낭비가 되는 것이다.

이러한 중복 요소를 줄이기 위해, HPACK을 사용해, 헤더 값을 테이블에 저장하고, 같은 값을 다시 보낼 때, 번호(인덱스)만 보내는 방식을 사용한다. HPACK은 헤더 이름과 값으로 Key-Value 형태로 구성되어 있다. 그리고, LRU 캐시처럼 새로운 값이 들어오면 오래된 값은 밀려나고 사라지는 특성도 갖고 있다.

서버 푸시

HTTP/1에서는 클라이언트는 단일 요청을 하고 단일 응답을 받았다. 하지만, HTTP/2에서는 서버 푸시를 통해, 서버가 하나 이상의 응답으로 요청에 답할 수 있게 되었다.

예를 들어 SSR 페이지의 경우, 서버에서 프론트 파일을 보내게 될텐데, 클라이언트가 html 파일을 요청하면, 서버에서는 css와 js도 함께 보내주는 것이다. 서버 푸시를 사용하면, 요청/응답 사이에 생기는 대기 시간을 줄일 수 있다.

하지만, 이미 캐싱된 데이터가 있음에도, 푸시가 될 수 있어 대역폭을 낭비할 수 있다는 단점이 있다. 언제 어떻게 푸시할지 결정하는 것이 최대한 활용하는 비결이 될 것이다.

댓글남기기